/*
 *  shnode_math.cpp
 *  shaderz_v3
 *
 *  Created by Anjali on 4/7/11.
 *  Copyright 2011 __MyCompanyName__. All rights reserved.
 *
 */
#include "shnode_math.h"

using namespace shaderz;

///////////////////////////////////////////////
/////// Constant node
///////////////////////////////////////////////
shNodeConstant::shNodeConstant( const std::string& InNodeName, float InConstVal[], int InElementCount )
	: ParentClass(InNodeName)
{	
	switch(InElementCount)
	{
	case 1:
		{
			linkStub* pNewStub = constructLinkStub("Out", SHIO_OUTPUT, SHST_CONST1VEC );
			pNewStub->value.constant1Vec = InConstVal[0];
			addOutputStub(pNewStub);
		}
		break;
		
	case 2:
		{
			linkStub* pNewStub = constructLinkStub("Out", SHIO_OUTPUT, SHST_CONST2VEC );
			pNewStub->value.constant2Vec[0] = InConstVal[0];
			pNewStub->value.constant2Vec[1] = InConstVal[1];
			addOutputStub(pNewStub);
		}
		break;

	case 3:
		{
			linkStub* pNewStub =constructLinkStub("Out", SHIO_OUTPUT, SHST_CONST3VEC );
			pNewStub->value.constant3Vec[0] = InConstVal[0];
			pNewStub->value.constant3Vec[1] = InConstVal[1];
			pNewStub->value.constant3Vec[2] = InConstVal[2];
			addOutputStub(pNewStub);
		}
		break;

	case 4:
		{
			linkStub* pNewStub = constructLinkStub("Out", SHIO_OUTPUT, SHST_CONST4VEC );
			pNewStub->value.constant3Vec[0] = InConstVal[0];
			pNewStub->value.constant3Vec[1] = InConstVal[1];
			pNewStub->value.constant3Vec[2] = InConstVal[2];
			pNewStub->value.constant3Vec[3] = InConstVal[3];
			addOutputStub(pNewStub);
		}
		break;
	}
}

void shNodeConstant::evaluate()
{
	// nothing to do 
}

#ifdef SH_DEBUG
#include <iostream>
void shNodeConstant::dumpNodeStats() const
{
	ParentClass::dumpNodeStats();
	
	std::cout<<"ConstValue: "<<mOutputStubs[0]->toString()<<std::endl;
}
#endif


///////////////////////////////////////////////
/////// Math operation node
///////////////////////////////////////////////
shNodeMath::shNodeMath( const std::string& InNodeName, MathOperation InMathOperation )
	: ParentClass(InNodeName)
	, mMathOperation(InMathOperation)
{
}

// evaluates the inputs before evaluating the result to be placed in the output nodes
void shNodeMath::evaluate()
{
	// process evaluation in parent class first
	ParentClass::evaluate();

	// initial setup of result node
	mOutputStubs[0]->clear();
	*mOutputStubs[0] = *mInputStubs[0];

	// make the corresponding calculations starting from second input stub (first has already been considered above)
	for( int ipIndex=1; ipIndex < mInputStubs.size(); ++ipIndex )
	{
		switch( mMathOperation )
		{
		case SHMO_Add:
			*mOutputStubs[0] = *mOutputStubs[0] + *mInputStubs[ipIndex];
			break;
			
		case SHMO_Subtract:
			*mOutputStubs[0] = *mOutputStubs[0] - *mInputStubs[ipIndex];
			break;
			
		case SHMO_Multiply:
			*mOutputStubs[0] = *mOutputStubs[0] * *mInputStubs[ipIndex];
			break;

		case SHMO_Division:
			*mOutputStubs[0] = *mOutputStubs[0] / *mInputStubs[ipIndex];
			break;
		}
	}
}

#ifdef SH_DEBUG
#include <iostream>
void shNodeMath::dumpNodeStats() const
{
	ParentClass::dumpNodeStats();
	
	std::cout<<"Operation: "<< mMathOperation<< std::endl;
}
#endif
